<?php
/**
 * 框架核心类，以静态方式来使用
 * 
 * @version $Id: App.php 206 2011-06-22 01:57:25Z linsir123 $
 */
class App
{
	/**
	 * @var 系统类列表，采用<<按需加载>>
	 */
	public static $__classes = array(
		'BASE' => array(
			// 基础流程类
			'Request' 			=> 'Request.php',
			'Dispatcher' 		=> 'Dispatcher.php',
			'AccessControll'	=> 'AccessControll.php',
			'Controller' 		=> 'Controller.php',
			
			// 服务提供类
			'ActiveRecord' 		=> 'ActiveRecord.php',
			'Config' 			=> 'Config.php',
			'Mysql' 			=> 'Mysql.php',
			'LMemcache' 		=> 'Memcache.php',
			'View' 				=> 'View/View.php',
			'I18n' 				=> 'I18n/I18n.php',
			'Soap' 				=> 'Service/Soap.php',
			'Wsdl' 				=> 'Service/Wsdl.php',
			
			// 功能函数类
			'lpString' 			=> 'Common/String.php',
			'lpSystem' 			=> 'Common/System.php',
			'lpFile' 			=> 'Common/File.php',
			'lpDir' 			=> 'Common/Dir.php',
			'lpUrl' 			=> 'Common/Url.php'
		),
		'OTHER' => array()
	);
	
	/**
	 * @var APP单例
	 */
	public static $__app = null;
	
	/**
	 * @var APP过程加载的文件数
	 */
	public static $__imports = array(__FILE__);
	
	/**
	 * @var APP实例对象集合
	 */
	public static $__instances = array();
	
	
	/// 以上属性为静态属性  ///
	
	
	/**
	 * @var 应用程序当前使用的目录，即子系统
	 */
	public $subApp = '';
	
	/**
	 * @var APP属性列表
	 */
	private $_options = array();
	
	/**
	 * 构造函数
	 */
	public function __construct()
	{
		$this->_options = self::import('Config/main.php');
		$options = self::import('Config/main.php', APP_DIR, false);
		if ($options && is_array($options)) {
			foreach ($options as $name => $value)
				$this->$name = $value;
		}
	}
	
	/**
	 * 设置选项
	 */
	public function __set($name, $value)
	{
		$this->_options[$name] = $value;
	}
	
	/**
	 * 取得选项
	 */
	public function __get($name)
	{
		if (isset($this->_options[$name]))
			return $this->_options[$name];
		else 
			throw new Exception("配置选项({$name})不存在。");
	}
	
	/**
	 * 将子系统配置选项复制到主系统中
	 */
	public function setSubApp($subApp)
	{
		$this->subApp = $subApp;
		$subApps = is_array($this->subApps) ? $this->subApps : array();
		$options = isset($subApps[$subApp]) ? $subApps[$subApp] : array();
		foreach ($options as $name => $value)
			$this->$name = $value;
	}
	
	/**
	 * 初始化应用程序
	 */
	public function run()
	{
		self::initContext();
		
		///
		lpSystem::hCharset($this->charset['html']);
		
		///
		self::getRequest()->init();
		self::getDispatcher()->dispatching();
		self::end();
	}
	
	
	/// 以下方法提供为静态调用  ///
	
	
	/**
	 * 结构模式：单件模式，即在整个系统中只有一个该类的对象
	 */
	static function instance()
	{
		if (!self::$__app) 
			self::$__app = new App();
		
		return self::$__app;
	}
	
	/**
	 * 配置类自动加载
	 */
	static function autoLoad($class)
	{
		$classes = self::$__classes;
		if (isset($classes['BASE'][$class])) 
			self::import($classes['BASE'][$class]);
		elseif (isset($classes['OTHER'][$class])) 
			self::import($classes['OTHER'][$class], null);
		else  
			throw new Exception("类({$class})所在文件不存在。");
	}
	
	/**
	 * 初始化上下文环境
	 * 
	 * 1、自定义错误和异常处理
	 * 2、关闭[magic_quotes_gpc]
	 * 3、设置默认时区
	 */
	static function initContext()
	{
		set_error_handler(array('lpSystem','errorHandler'), E_ALL);
		set_exception_handler(array('lpSystem','exceptionHandler'));
		
		/// 
		if (get_magic_quotes_gpc()) {
			$_GET = lpString::stripslashes($_GET);
			$_POST = lpString::stripslashes($_POST);
			$_COOKIE = lpString::stripslashes($_COOKIE);
		}
		
		/// 
		if (function_exists('date_default_timezone_set')) 
			date_default_timezone_set('Asia/ShangHai');
	}
	
	/**
	 * 结束应用并输出结果
	 */
	static function end()
	{
		if (self::isSingleton('View')) 
			self::getView()->render();
			
		exit();
	}
	
	/**
	 * 注册类以更自动加载
	 */
	static function registerClass($class, $file)
	{
		self::$__classes['OTHER'][$class] = $file;
	}
	
	/**
	 * 加载文件
	 */
	static function import($file, $dir = CORE_DIR, $throw = true)
	{
		$file = $dir.$file;
		if (!in_array($file, self::$__imports)) {
			array_push(self::$__imports, $file);
			if (file_exists($file)) 
				return require($file);
				
			///
			if ($throw) 
				throw new Exception("文件({$file})不存在。");
		}
		
		return false;
	}
	
	/**
	 * 判断某个类是否实例化
	 */
	static function isSingleton($class)
	{
		return isset(self::$__instances[$class]);
	}
	
	/**
	 * 取得某个类的实例化对象
	 */
	static function singleton($class, $params = array(), $key = null)
	{
		if (!class_exists($class)) 
			throw new Exception("类({$class})不存在。");
			
		///
		$key = $class.$key;
		if (isset(self::$__instances[$key])) 
			return self::$__instances[$key];
			
		$reflection = new ReflectionClass($class);
		$singleton = call_user_func_array(array(& $reflection, 'newInstance'), $params);
		self::$__instances[$key] = $singleton;
		
		return $singleton;
	}
	
	/**
	 * 取得[Mysql]对象
	 */
	static function getMysql($dsnNumber = 0)
	{
		return self::singleton('Mysql', array($dsnNumber), $dsnNumber);
	}
	
	/**
	 * 取得[Memcache]对象
	 */
	static function getMc()
	{
		return self::singleton('LMemcache');
	}
	
	/**
	 * 取得配置对象
	 */
	static function getConf()
	{
		return self::singleton('Config');
	}
	
	/**
	 * 取得视图对象
	 */
	static function getView()
	{
		return self::singleton('View');
	}
	
	/**
	 * 取得多语言对象
	 */
	static function getI18n()
	{
		return self::singleton('I18n');
	}
	
	/**
	 * 取得消息调度器对象
	 */
	static function getDispatcher()
	{
		return self::singleton('Dispatcher');
	}
	
	/**
	 * 取得HTTP请求信息处理对象
	 */
	static function getRequest()
	{
		return self::singleton('Request');
	}
	
	/**
	 * 取得访问控制处理对象
	 */
	static function getAccessControll()
	{
		return self::singleton('AccessControll');
	}
	
	/**
	 * 返回一个模型对象
	 */
	static function M($model, $fieldId = 0)
	{
		$class = 'model'.$model;
		$file = APP_DIR.'Model/'.$model.'.php';
		self::registerClass($class, $file);
		
		///
		$params = empty($fieldId) ? array() : array($fieldId);
		return self::singleton($class, $params);
	}
	
	/**
	 * 返回一个组件对象
	 * 
	 * 需要传入类构造函数的参考，可以从第二个参数开始
	 */
	static function C($component)
	{
		$class = 'com'.$component;
		$file = CORE_DIR.'Component/'.$component.'.php';
		self::registerClass($class, $file);
		
		///
		$params = func_get_args();
		array_shift($params);
		return self::singleton($class, $params);
	}
	
	/**
	 * 加载一个第三方入口文件
	 */
	static function V($vendor)
	{
		$file = 'Vendors/'.strtolower($vendor).'.php';
		self::import($file, APP_DIR, false) or self::import($file, BASE_DIR);
	}
	
	/**
	 * 日志处理
	 */
	static function log($content, $name = 'debug')
	{
		$dir = CACHE_DIR.$name;
		lpDir::make($dir);
		
		///
		$content = is_string($content) ? $content : var_export($content, true);
		lpFile::log("{$dir}/log.log", 
			date('Y-m-d h:i:s')." {$content}\r\n", 'a+', 
			10240);
	}
	
	/**
	 * 应用上下文信息
	 */
	static function info()
	{
		list($usec, $sec) = explode(' ', TIME_START);
		$timeStart = ((float)$usec + (float)$sec);
		list($usec, $sec) = explode(' ', microtime());
		$info = array(
			'memory'=>memory_get_usage(),
			'time'=>((float)$usec + (float)$sec) - $timeStart
		);
		
		///
		if (APP_DEBUG) {
			$dbo = array('numQuery'=>0, 'queries'=>array());
			if (self::isSingleton('Mysql')) {
				$dbo['numQuery'] = self::getMysql()->numQuery;
				$dbo['queries'] = self::getMysql()->queries;
			}
			
			$info['imports'] = self::$__imports;
			$info['dbo'] = $dbo;
		}
		
		return $info;
	}
}
